﻿/// <reference path="ref.js" />
/// <reference path="application.js" />
/// <reference path="sprite.js" />
/// <reference path="scene.js" />
/// <reference path="rope.js" />


function Worm() {
    // Initialize default position
    this.x = 580;
    this.y = 120;

    this.yreal = this.y;
    this.xreal = this.x;
    this.vy = 0;

    this.jumpCounterDelay = 3;
    this.jumpVisualStateCounter = 0;

    this.viewFinderAngle = 0;

    // Initialize default direction
    this.direction = Direction.left;

    // Initialize worm sprite
    this.sprite = new Sprite(app.context.rootUrl + "sprites/worm.png");
    this.sprite.rowLenght[WormVisualStates.WalkCycleForward] = 10;
    this.sprite.rowLenght[WormVisualStates.WalkCycleUp] = 10;
    this.sprite.rowLenght[WormVisualStates.WalkCycleDown] = 10;
    this.sprite.rowLenght[WormVisualStates.Jump] = 5;
    this.sprite.rowIndex = 0;
    this.sprite.sourceW = 64;
    this.sprite.sourceH = 64;
    this.sprite.centerX = 32;
    this.sprite.centerY = 32;
    this.sprite.isInDebugMode = false;

    // relative to center in world coordinate
    this.collisionX = 0;
    this.collisionY = -13;
    this.isInCollision = false;

    // collision points on which hit test is performed
    this.collisions = {
        groundGluerUp: { x: 0, y: -8, hitTest: false },
        groundGluerDown: { x: 0, y: -9, hitTest: false },
        groundSlopeLeftUp: { x: -6, y: -10, hitTest: false },
        groundSlopeLeftDown: { x: -6, y: -11, hitTest: false },
        groundSlopeRightUp: { x: 6, y: -10, hitTest: false },
        groundSlopeRightDown: { x: 6, y: -11, hitTest: false }
    };

    /// [Rope]
    this.rope = null;
    
    if (typeof Worm.initialized == "undefined") {

        /// Jump method
        Worm.prototype.Jump = function () {
            this.vy += 30 / app.context.frameRate;
        };

        /// ViewFinder up method
        Worm.prototype.ViewFinderUp = function () {
            this.viewFinderAngle += 10;
            if (this.viewFinderAngle > 90) {
                this.viewFinderAngle = 90;
            }
        };

        /// ViewFinder down method
        Worm.prototype.ViewFinderDown = function() {
            this.viewFinderAngle -= 10;
            if (this.viewFinderAngle < -80) {
                this.viewFinderAngle = -80;
            }
        };

        /// Go right method
        Worm.prototype.GoRight = function () {
            this.direction = Direction.right;
            this.x++;

            // Increase rowindex if the worm is walking
            if (this.sprite.rowIndex == WormVisualStates.WalkCycleForward || this.sprite.rowIndex == WormVisualStates.WalkCycleDown || this.sprite.rowIndex == WormVisualStates.WalkCycleUp) {
                this.sprite.StepForward();
            }
        };

        /// Go left method
        Worm.prototype.GoLeft = function () {
            this.direction = Direction.left;
            this.x--;
            
            // Increase rowindex if the worm is walking
            if (this.sprite.rowIndex == WormVisualStates.WalkCycleForward || this.sprite.rowIndex == WormVisualStates.WalkCycleDown || this.sprite.rowIndex == WormVisualStates.WalkCycleUp) {
                this.sprite.StepForward();
            }
        };
        
        /// Draws the viewFinder
        Worm.prototype.DrawViewFinder = function () {
            var radAngle = this.viewFinderAngle * Math.PI / 180;

            window.app.context.container2d.strokeStyle = "black";
            window.app.context.container2d.lineWidth = 3;
            window.app.context.container2d.beginPath();
            window.app.context.container2d.moveTo(app.UI.ToScreenX(this.x) + Math.cos(-radAngle) * 20 * this.direction, app.UI.ToScreenY(this.y) + Math.sin(-radAngle) * 20);
            window.app.context.container2d.lineTo(app.UI.ToScreenX(this.x) + Math.cos(-radAngle) * 25 * this.direction, app.UI.ToScreenY(this.y) + Math.sin(-radAngle) * 25);
            window.app.context.container2d.lineCap = "round";
            window.app.context.container2d.closePath();
            window.app.context.container2d.stroke();
        };

        /// Entity Draw method
        Worm.prototype.Draw = function () {

            // Process hit tests
            this.ProcessHitTest();

            // Set sprite position
            this.sprite.x = this.x;
            this.sprite.y = this.y;

            // Compute scale from direction
            this.sprite.scaleX = this.direction == Direction.left ? 1 : -1;

            // jump situation if vy != 0;
            if (this.vy != 0) {
                if (this.sprite.rowIndex != WormVisualStates.Jump && (++this.jumpVisualStateCounter) > this.jumpCounterDelay) {
                    this.sprite.rowIndex = WormVisualStates.Jump;
                    this.sprite.Reset();
                }
                this.sprite.StepForward(false);
            }
            else if (this.sprite.rowIndex == WormVisualStates.Jump) {
                this.sprite.rowIndex = WormVisualStates.WalkCycleForward;
                this.sprite.Reset();
            }

            // Case in which jump counter must be reset
            if (this.sprite.rowIndex == WormVisualStates.Jump
                || this.sprite.rowIndex != WormVisualStates.Jump && this.vy == 0) {
                this.jumpVisualStateCounter = 0;
            }

            // Compute WormVisualStates
            switch (this.sprite.rowIndex) {

                // Walk forward case: continue this way until a down detector is no more hitten             
                case WormVisualStates.WalkCycleForward:
                    if (!this.collisions.groundSlopeLeftDown.hitTest && this.collisions.groundSlopeRightDown.hitTest) {
                        this.sprite.rowIndex = (this.direction == Direction.left) ? WormVisualStates.WalkCycleDown : WormVisualStates.WalkCycleUp;
                        this.sprite.Reset();
                    }
                    else if (!this.collisions.groundSlopeRightDown.hitTest && this.collisions.groundSlopeLeftDown.hitTest) {
                        this.sprite.rowIndex = (this.direction == Direction.left) ? WormVisualStates.WalkCycleUp : WormVisualStates.WalkCycleDown;
                        this.sprite.Reset();
                    }
                    break;

                // Walk up case             
                case WormVisualStates.WalkCycleUp:
                    if (this.direction == Direction.right && this.collisions.groundSlopeLeftUp.hitTest
                        || this.direction == Direction.left && this.collisions.groundSlopeRightUp.hitTest) {
                        this.sprite.rowIndex = WormVisualStates.WalkCycleForward;
                        this.sprite.Reset();
                    }
                    break;

                // Walk down case              
                case WormVisualStates.WalkCycleDown:
                    if (this.direction == Direction.right && this.collisions.groundSlopeRightUp.hitTest
                        || this.direction == Direction.left && this.collisions.groundSlopeLeftUp.hitTest) {
                        this.sprite.rowIndex = WormVisualStates.WalkCycleForward;
                        this.sprite.Reset();
                    }
                    break;

                default:
                    // no default case
                    break;
            }

            // draw the sprite
            this.sprite.Draw();

            // draw debug info
            if (app.context.isInDebugMode) {
                // hit test
                for (pointIndex in this.collisions) {
                    window.app.context.container2d.fillStyle = this.collisions[pointIndex].hitTest ? "red" : "black";
                    window.app.context.container2d.fillRect(
                app.UI.ToScreenX(this.x + this.collisions[pointIndex].x) - 1,
                app.UI.ToScreenY(this.y + this.collisions[pointIndex].y) - 1,
                2, 2);
                }

                // velocity
                window.app.context.container2d.font = "9px arial";
                window.app.context.container2d.textAlign = "left";
                window.app.context.container2d.fillStyle = "#333333";
                app.context.container2d.fillText("velocity = " + this.vy, app.UI.ToScreenX(this.x - this.sprite.centerX), app.UI.ToScreenY(this.y + this.sprite.centerY + 12));
                app.context.container2d.fillText("viewF angle = " + this.viewFinderAngle + "°", app.UI.ToScreenX(this.x - this.sprite.centerX), app.UI.ToScreenY(this.y + this.sprite.centerY + 21));
            }

            this.DrawViewFinder();

            if (this.rope) {
                this.rope.Draw();
            }
        };

        /// Entity Think method
        Worm.prototype.Think = function () {
            //this.ProcessHitTest();

            // gravity effect
            this.vy += app.context.gravity / app.context.frameRate;
            //if (this.rope) { this.vy += this.rope.strength.y; };
            this.yreal += this.vy;
            this.y = Math.round(this.yreal);
            this.ProcessHitTest();

            this.ProcessHitTest(this.collisions.groundGluerUp);
            if (this.collisions.groundGluerUp.hitTest) {
                this.vy = 0;
                //this.ProcessHitTest();
                while (this.collisions.groundGluerUp.hitTest) {
                    this.y++;
                    this.ProcessHitTest(this.collisions.groundGluerUp);
                }
                this.yreal = this.y;
            }

            this.ProcessHitTest(this.collisions.groundGluerDown);
            if (this.collisions.groundGluerDown.hitTest) {
                this.vy = 0;
                this.yreal = this.y;
            }

            if (this.rope) {
                this.rope.x = this.x;
                this.rope.y = this.y;
                this.rope.Think();
            }
        };


        /// Processes Hit tests for each collision point
        Worm.prototype.ProcessHitTest = function () {
            // Process hitTest for on point
            if (arguments[0] && arguments[0].x && arguments[0].y) {
                arguments[0].hitTest = app.data.scene.isInCollision(
                    this.x + arguments[0].x,
                    this.y + arguments[0].y);
            }
            // Process hit test for all points
            else {
                for (pointIndex in this.collisions) {
                    this.collisions[pointIndex].hitTest = app.data.scene.isInCollision(
                        this.x + this.collisions[pointIndex].x,
                        this.y + this.collisions[pointIndex].y);
                }
            }
        };


        /// Toggles ninja rope
        Worm.prototype.ToggleRope = function () {
            if (this.rope) {
                this.DeactivateRope();
            } else {
                this.ActivateRope();
            }
        };

        Worm.prototype.ActivateRope = function () {
            this.rope = new Rope(this.x, this.y, this.direction == Direction.right ? this.viewFinderAngle : 180 - this.viewFinderAngle);
        };

        Worm.prototype.DeactivateRope = function () {
            this.rope = null;
        };
 
		Worm.initialized = true;
	}
};